package cn.xiaolang.thread.lock;

/**
 * 判定synchronized是否是可重入锁
 *
 * @author fuhw/DeanKano
 * @date 2019-01-08
 */
public class SynchronizedIsReentrantLock extends FatherWorker {
	
	/**
	 * 这里的对象锁只有一个,就是 child 对象的锁,
	 * 1 当执行 child.doSomething 时，该线程获得 child 对象的锁,在 doSomething 方法内执行 doAnotherThing 时再次请求child对象的锁，
	 * 因为synchronized 是重入锁，所以可以得到该锁，
	 * 2 继续在 doAnotherThing 里执行父类的 doSomething 方法时第三次请求 child 对象的锁，同样可得到。
	 * 如果不是重入锁的话，那这后面这两次请求锁将会被一直阻塞，从而导致死锁。
	 * 所以在 java 内部，同一线程在调用自己类中其他 synchronized 方法/块或调用父类的 synchronized 方法/块都不会阻碍该线程的执行。
	 * 就是说同一线程对同一个对象锁是可重入的，而且同一个线程可以获取同一把锁多次，也就是可以多次重入。
	 * 因为java线程是基于“每线程（per-thread）”，而不是基于“每调用（per-invocation）”的
	 * （java中线程获得对象锁的操作是以线程为粒度的，per-invocation 互斥体获得对象锁的操作是以每调用作为粒度的）
	 * 
	 * @param args
	 * @author fuhw/DeanKano
	 */
	public static void main(String[] args) {
		SynchronizedIsReentrantLock lock = new SynchronizedIsReentrantLock();
		lock.doSomething();
	}

	@Override
	public synchronized void doSomething() {
		System.out.println("child.doSomething()" + Thread.currentThread().getName());
		// 调用自己类中其他的synchronized方法
		doAnotherThing(); 
	}

	private synchronized void doAnotherThing() {
		// 调用父类的synchronized方法
		super.doSomething(); 
		System.out.println("child.doAnotherThing()" + Thread.currentThread().getName());
	}
}

class FatherWorker {

	public synchronized void doSomething() {
		System.out.println("father.doSomething()" + Thread.currentThread().getName());
	}
}